package com.ruoyi.system.xcenter.endpoints;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.http.HttpUtil;
import com.ruoyi.common.json.JSON;
import com.ruoyi.common.json.JSONObject;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.system.domain.DataxBizOrder;
import com.ruoyi.system.mapper.DataxBizOrderMapper;
import com.ruoyi.system.xcenter.EPContext;
import com.ruoyi.system.xcenter.IEndPoint;
import com.ruoyi.system.xcenter.PassiveEndPointAbstract;
import com.ruoyi.system.xcenter.exception.DataXException;
import com.ruoyi.system.xcenter.utils.RSAUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerEndpoint;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.Date;

@Component
public class XindianEndPoint extends PassiveEndPointAbstract implements IEndPoint {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private DataxBizOrderMapper bizOrderMapper;

    @Override
    public Object dataUpload(EPContext context,Object body,Integer type) throws Exception {
        StringBuilder res = new StringBuilder();
        if(body instanceof JSONObject.JSONArray){
            JSONObject.JSONArray list = (JSONObject.JSONArray) body;
            for (Object obj : list) {
                res.append(postXindian(context, obj, type));
            }
        }else {
            res.append(postXindian(context, body, type));
        }

        return res.toString();
    }

    private String postXindian(EPContext context, Object body, Integer type) throws Exception {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("accessName", context.getPlatform().getAccessname());
        String dataStr = RSAUtil.encryptByPrivateKey(JSON.marshal(body), context.getPlatform().getAccountPwdUp());
        jsonObject.put("data", dataStr);
        jsonObject.put("sign", RSAUtil.sign(dataStr, context.getPlatform().getAccountPwdUp()));
        logger.info("xindian push {}",jsonObject);
        String suffix = null;
        switch (type){
            case 1: //心跳接口
                suffix = "/heartThrob";
                break;
            case 2: // 入场事件
                suffix = "/parkpot/park";
                break;
            case 3: // 出场事件
                suffix = "/parkpot/leave";
                break;
            case 4: // 主动扣费
                suffix = "/pay/parkpot/toAutoPay";
                break;
            case 5: // 无牌车进场通知
                suffix = "/confirm/confirmUnlicensedNotifyByPark";
                break;
            case 6: // 无牌车出场通知
                suffix = "/business/uploadGateBusinessInfo";
                break;
            case 7: // 无感验签接口
                suffix = "/business/querySign";
                break;
            case 8: // 支付通知确认
                suffix = "/pay/confirmPayNotify";
                break;
            default:
                logger.warn("未对接的接口类型,{}", type);
                break;
        }
        String res = HttpUtil.post(context.getPlatform().getDataUploadUrl() + suffix, JSON.marshal(jsonObject),6000);
        Integer code = JSON.unmarshal(res, JSONObject.class).getInt("result");
        if(type.equals(4)){ // 主动支付结果回存
            JSONObject tmp = (JSONObject) body;
            String orderNo = tmp.getStr("outTradeNo");
            DataxBizOrder bizOrder = bizOrderMapper.selectDataxBizOrderByOrderId(orderNo);
            bizOrder.setResPay(res);
            // 扣款状态更新
            if(code==0){
                String data = JSON.unmarshal(res, JSONObject.class).getStr("data");
                String isPass = JSON.unmarshal(data, JSONObject.class).getStr("isPass");
                if("1".equals(isPass)){
                    //bizOrder.setStatus(2);
                    bizOrder.setFlag(1);
                }
            }

            bizOrderMapper.updateDataxBizOrder(bizOrder);
        }
        if(code!=0){
            throw new DataXException(res);
        }
        return res;
    }

    @Override
    public Object dataDownload( EPContext context,Object request, Integer type) throws Exception {

        //this.consumeEndPoint(decrypt,type);
        return null;
    }

    /**
     * 初始化MQ监听器
     */
    public void init(EPContext context){
        rabbitMqStarter(context);
    }

    private void rabbitMqStarter(EPContext context){
        CachingConnectionFactory factory = new CachingConnectionFactory();
        factory.setUri(context.getPlatform().getDataDownloadUrl());
        SimpleRabbitListenerContainerFactory listenerContainerFactory = new SimpleRabbitListenerContainerFactory();
        listenerContainerFactory.setConnectionFactory(factory);
//        listenerContainerFactory.setAutoStartup(true);
        SimpleRabbitListenerEndpoint endpoint = new SimpleRabbitListenerEndpoint();
        endpoint.setQueueNames("yctc-getBusinessInfo-jstc"
                ,"yctc-payNotify-jstc"
                ,"yctc-unlicensedNotifyByPark-jstc"
                ,"yctc-getGateBusinessInfo-jstc"
                ,"yctc-calculateFee-jstc");
        endpoint.setMessageListener(message -> {
            String queue = message.getMessageProperties().getConsumerQueue();

            String result = new String(message.getBody(), StandardCharsets.UTF_8);
            logger.info("MQ监听主题：{},消息体：{}",queue,result);

            try {
                JSONObject marshal = JSON.unmarshal(result,JSONObject.class);
                Long requestId = marshal.getLong("requestId");
                String data = marshal.getStr("data");
                RSA rsa = SecureUtil.rsa(cn.hutool.core.codec.Base64.decode(context.getPlatform().getAccountPwdUp()), cn.hutool.core.codec.Base64.decode(context.getPlatform().getAccountUserUp()));
                String decrypt =rsa.decryptStr(data, KeyType.PrivateKey);
                logger.info("MQ解密：{}",decrypt);
                JSONObject unmarshal = JSON.unmarshal(decrypt, JSONObject.class);
                JSONObject json = new JSONObject();
                Integer type = 0;
                switch (queue){
                    case "yctc-payNotify-jstc":
                        // 支付结果确认
                        json.put("requestId",requestId);
                        json.put("success",true);
                        try {
                            // 订单库更新
                            String outTradeNo = unmarshal.getStr("outTradeNo");
                            String payNo = unmarshal.getStr("payid");
                            DataxBizOrder bizOrder = bizOrderMapper.selectDataxBizOrderByOrderId(outTradeNo);
                            if(bizOrder!=null){
                                bizOrder.setResPayNotify(decrypt);
                                bizOrder.setPayNo(payNo);
                                bizOrderMapper.updateDataxBizOrder(bizOrder);
                            }else {
                                logger.info("支付确认异常，订单无记录对应,{}",outTradeNo);
                            }
                            String payNotifyByPark = postXindian(context, json, 8);
                            logger.info("支付结果确认，{}",payNotifyByPark);
                        } catch (Exception e) {
                            logger.error("支付结果确认异常，{}",e.getMessage());
                        }
                        break;
                    case "yctc-unlicensedNotifyByPark-jstc":
                        // 不支持无牌车的确认返回
                        json.put("requestId",requestId);
                        json.put("success",true);
                        try {
                            String unlicensedNotifyByPark = postXindian(context, json, 5);
                            logger.info("捷顺无牌车in暂不支持，{}",unlicensedNotifyByPark);
                        } catch (Exception e) {
                            logger.error("捷顺无牌车in暂不支持，{}",e.getMessage());
                        }
                        break;
                    case "yctc-getGateBusinessInfo-jstc":
                        // 不支持无牌车的确认返回
                        json.put("requestId",requestId);
                        json.put("success",true);
                        JSONObject params = new JSONObject();
                        if(StringUtils.isNotEmpty(unmarshal.getStr("scanUserTag"))){
                            // 无牌车处理
                            params.put("status","2");
                            params.put("extBusinessId", UUID.randomUUID().toString(true));
                            params.put("plateNo","无牌车不支持");
                            params.put("plateType","2");
                            params.put("paymentTotal",0);
                            params.put("holdingTime",0);
                            params.put("totalFee",0);
                            params.put("parkTime", DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",new Date()));
                            params.put("leaveTime",DateUtils.parseDateToStr("yyyy-MM-dd HH:mm:ss",new Date()));
                        }else{
                            // 有牌车处理

                        }

                        json.put("params",params);
                        try {
                            String getGateBusinessInfo = postXindian(context, json, 6);
                            logger.info("捷顺无牌车out暂不支持，{}",getGateBusinessInfo);
                        } catch (Exception e) {
                            logger.error("捷顺无牌车out暂不支持，{}",e);
                        }
                        break;
                }

                dataDownload(context,result,type);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
        SimpleMessageListenerContainer container = listenerContainerFactory.createListenerContainer(endpoint);
        container.start();
        logger.info("MQ监听已启动.{}",context.getPlatform().getDataDownloadUrl());
    }


}
